Vue 3 is in beta and it’s subject to change.
Vue 3 is the up and coming version of Vue front end framework.
It builds on the popularity and ease of use of Vue 2.
In this article, we’ll look at slot shorthands with Vue 3.
Shorthand Syntax for Default Slots
If we have one slot, then we don’t need the template
element.
We can put the v-slot
directive right on the opening component tag.
For instance, we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<items v-slot="slotProps">
<b>{{ slotProps.item.name }}</b>
</items>
</div>
<script>
const app = Vue.createApp({});
app.component("items", {
template: `
<ul>
<li v-for="( item, index ) in items">
<slot v-bind:item="item"></slot>
</li>
</ul>
`,
data() {
return {
items: [{ name: "apple" }, { name: "orange" }, { name: "grape" }]
};
}
});
app.mount("#app");
</script>
</body>
</html>
We have the v-slot
directive on the component tag, which is only allowed when we have one slot in our component.
Destructuring Slot Props
Slot props can be destructured.
Since we have an object as the value of v-slot
, we can destructure its properties.
For example, we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<items v-slot="{ item: { name } }">
<b>{{ name }}</b>
</items>
</div>
<script>
const app = Vue.createApp({});
app.component("items", {
template: `
<ul>
<li v-for="( item, index ) in items">
<slot v-bind:item="item"></slot>
</li>
</ul>
`,
data() {
return {
items: [{ name: "apple" }, { name: "orange" }, { name: "grape" }]
};
}
});
app.mount("#app");
</script>
</body>
</html>
We destructured the properties of the slotProps
object, so instead of writing:
<items v-slot="slotProps">
<b>{{ slotProps.item.name }}</b>
</items>
we have:
<items v-slot="{ item: { name } }">
<b>{{ name }}</b>
</items>
This can make templates much cleaner especially if we have many slots.
It’s also easy for us to provide fallbacks.
For example, we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<items v-slot="{ item: { name = 'placeholder' } }">
<b>{{ name }}</b>
</items>
</div>
<script>
const app = Vue.createApp({});
app.component("items", {
template: `
<ul>
<li v-for="( item, index ) in items">
<slot v-bind:item="item"></slot>
</li>
</ul>
`,
data() {
return {
items: [{ name: "apple" }, { name: "orange" }, {}]
};
}
});
app.mount("#app");
</script>
</body>
</html>
We set the default value of the name
property to 'placeholder'
so that we can display that if nothing is set for the name
property.
Dynamic Slot Names
Slot names can be dynamic.
So we can write:
<base-layout>
<template v-slot:[dynamicSlotName]>
...
</template>
</base-layout>
where dynamicSlotName
is the variable with the slot name.
Named Slots Shorthand
Named slots can be shorted with the #
sign.
For example, instead of writing:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<blog-post>
<template v-slot:header>
<h1>header</h1>
</template>
<template v-slot:default>
<p>lorem ipsum.</p>
</template>
<template v-slot:footer>
<p>footer</p>
</template>
</blog-post>
</div>
<script>
const app = Vue.createApp({});
app.component("blog-post", {
template: `
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
`
});
app.mount("#app");
</script>
</body>
</html>
We can write:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<blog-post>
<template #header>
<h1>header</h1>
</template>
<template #default>
<p>lorem ipsum.</p>
</template>
<template #footer>
<p>footer</p>
</template>
</blog-post>
</div>
<script>
const app = Vue.createApp({});
app.component("blog-post", {
template: `
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
`
});
app.mount("#app");
</script>
</body>
</html>
#
is short for v-slot:
.
Conclusion
There’s a shorthand for named slots and also there’s a shorthand for default slots.